import logging


from django.contrib.auth.models import User
from django.core.serializers import get_serializer

from django.http import HttpResponse

from django.views import View
from django_redis import get_redis_connection
from rest_framework import status
from rest_framework.decorators import action
from rest_framework.mixins import ListModelMixin
from rest_framework.permissions import IsAuthenticated

from rest_framework.response import Response
from rest_framework.status import HTTP_400_BAD_REQUEST

from rest_framework.viewsets import GenericViewSet, ReadOnlyModelViewSet, ModelViewSet
from rest_framework_extensions.cache.mixins import CacheResponseMixin
from rest_framework_simplejwt.views import TokenObtainPairView

from config.dbs.redisConfig import KEY_TEMPLATE,EXPIRE_TIME
from users.models import Area, Address
from users.serializers import UserSerializer, MyTokenObtainSerializer, UserDetailSerializer, UpdatePasswordSerializer, \
    AreaSerializer, AddressSerializer, ParentAreaSerializer
from utils.verifyUtil import ImageVerifyUtil
from fdfs_client.client import Fdfs_client,get_tracker_conf
import io
# Create your views here.

# 创建日志对象
logger = logging.getLogger('__name__')
# 创建fastdfs客户端对象
tracker_path =  get_tracker_conf("fastdfs/client.conf")

# 通过配置文件地址  创建fafsdfs的客户端
client = Fdfs_client(tracker_path)


# 图片验证码类视图
# 127.0.0.1:8000/users/verification/uuid  get

class   ImageVerifyView(View):
    # 客户端发送get 请求的时候
    # 返回出去
    def get(self, request,func,uuid):
        imageVerifyUtil = ImageVerifyUtil()
        img, code = imageVerifyUtil.verify_code()
        # 内存中
        # 字节流 进行临时存储 不会持久化数据
        # 不需要要进行序列化
        img_bytes = io.BytesIO()  # 生成临时的字节文件
        img.save(img_bytes, format='PNG')  #吧图片保存到临时的字节文件中
        # 读取字节数据 返回到客户端
        res = img_bytes.getvalue()  # 读取文件内容

        # 存储进入redis # 获取redis缓存对象
        cache = get_redis_connection(alias="verify_codes")
        # 通过redis缓存对象 进行set 存储数据
        cache.set(KEY_TEMPLATE % (func,uuid),code,EXPIRE_TIME)

        return HttpResponse(res, content_type='image/png')


# 注册的逻辑
class UserViewSet(GenericViewSet):
    queryset = User.objects.all()
    serializer_class = UserSerializer


    # 重写序列化器的选择
    def get_serializer_class(self):
        if self.action == 'info':
            return UserDetailSerializer
        elif self.action == 'password':
            return  UpdatePasswordSerializer
        else:
            return UserSerializer

    # 权限问题
    # now 方法  是不是只能登录的用户来调用
    # create方法  不需要登录也能调用
    def get_permissions(self):
        if self.action in ["now","info"]:
            # 就需要进行登录
            permission_classes = [IsAuthenticated]
        else:
            permission_classes = []

        # 后期可能存在多个权限的调用
        return [permission() for permission in permission_classes]


    # 用户详情  只能查自己的用户详情
    @action(methods=["get"], detail=False)
    def now(self,request):
        serializer = self.get_serializer(request.user) # 得不到用户信息  类型错误  dict字典

        return Response(serializer.data)

    # 创建用户
    # 重写create
    def create(self, request, *args, **kwargs):
        # 进行反序列化
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        # 获取客户端数据
        username = request.data.get('username')
        password = request.data.get('password')
        # 进行持久化操作
        user = User(username=username)
        # 加密
        user.set_password(password)
        user.save()
        # 返回创建信息
        serializer = self.get_serializer(user)
        return Response(serializer.data)






    # 修改用户信息 肯定是当前的这个用户
    # 127.0.0.1:8000/user/users/info
    @action(methods=["put"], detail=False)
    def info(self,request):
        # 得到当前的用户信息
        user = request.user
        # 修改的是当前的用户  是否允许修改前端传入post提交的数据
        request.POST._mutable = True
        # user.id 得到的是当前登录的id
        request.data["user"] = user.id

        # 新增头像操作
        # 得到客户端传入的头像数据
        file = request.FILES.get('file')
        # 判断是否存在文件数据
        if file:
        # 判断是否是图片
            if file.content_type not in ['image/png','image/jpeg']:
                return Response(status=status.HTTP_400_BAD_REQUEST)
            try:
                # 如果没有文件后缀 1.png
                image_ext_name = file.name.split('.')[-1] # ["1" , "png"]
            except Exception as e:
                logger.info(f"图片的扩展名异常{e}")
                image_ext_name = "png"
            # 进行持久化存储  storage（存储服务端）
            try:
                # upload_by_filename  ==> upload_by_buffer
                # 数据 和文件的后缀  ===》 storage  ===》xxxxxx.png
                uploade_res = client.upload_by_buffer(file.read(),file_ext_name=image_ext_name)
            except Exception as e:
                logger.error(f"图片上传出现异常{e}")
                return Response(status=status.HTTP_500_INTERNAL_SERVER_ERROR)
            else:
                # 再进行数据库的持久化存储  图片地址
                if uploade_res.get("Status") != "Upload successed.":
                    logger.warning("图片上传失败")
                    return Response(status=status.HTTP_500_INTERNAL_SERVER_ERROR)
                else:
                    # 字节文件  ===》 字符文件
                    image_url = uploade_res.get("Remote file_id").decode()
                    request.data["avatar"] = image_url

        # 已经存在用户详情  修改
        if hasattr(user,"userdetail"):
            if user.userdetail.avatar:
                try:
                    client.delete_file(user.userdetail.avatar.encode())
                except Exception as e:
                    logger.error(f"Failed to delete old avatar: {e}")
            user_detail_serializer = self.get_serializer(instance=user.userdetail, data=request.data)
        else:
            # 没有用户详情  新增
            user_detail_serializer = self.get_serializer(data=request.data)
        user_detail_serializer.is_valid(raise_exception=True)
        user_detail_serializer.save()
        return Response(user_detail_serializer.data)





    @action(methods=["put"], detail=False)
    def password(self,request):
        # 获取当前登录的用户
        user = request.user
        # 获取传入的密码 进行反序列化校验
        serializer = self.get_serializer(data = request.data)
        serializer.is_valid(raise_exception=True)
        # 判断用户密码是否正确
        password = request.data["password"]
        new_password = request.data["new_password"]
        # 判断原密码是否正确
        if user.check_password(password):
            user.set_password(new_password)
            user.save()
            return Response({'msg':"密码修改成功"})
        else:
            return Response(status = HTTP_400_BAD_REQUEST)



#登录的视图逻辑
class MyTokenObtainViews(TokenObtainPairView):
    serializer_class = MyTokenObtainSerializer


# 地址视图　
# redis 有时效性的  热点数据
#       数据缓存操作  针对读取多  修改少的

# class AreaViewSet(GenericViewSet,ListModelMixin):
class AreaViewSet(CacheResponseMixin,ReadOnlyModelViewSet):
    queryset = Area.objects.all()
    serializer_class = AreaSerializer
    permission_classes = [IsAuthenticated]

    # 没有指定id的查询  查所有的一级分类

    def get_queryset(self):
        if self.action == 'list':
            return self.queryset.filter(parent=None)
        else:
            return self.queryset

    def get_serializer_class(self):
        if self.action == 'list':
            # return AreaSerializer
            return self.serializer_class
        else:
            return ParentAreaSerializer


# 详情地址
class AddressViewSet(ModelViewSet):
    queryset = Address.objects.filter(is_delete=False)
    serializer_class = AddressSerializer
    permission_classes = [IsAuthenticated]


    # 重写create
    def create(self, request, *args, **kwargs):
        # 选择性的优化
        # 地址 max = 10
        if self.queryset.filter(is_delete=False).count() >=  10:
            return Response({
                "detail":"收货地址数量超过最大10个的限制"
            },status=HTTP_400_BAD_REQUEST)
        request.POST._mutable = True # 运行修改post提交的数据
        request.data["user"] = request.user.id

        return ModelViewSet.create(self, request, *args, **kwargs)



